package com.yq.testmodule.recycleview

import android.animation.ValueAnimator
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutManager
import androidx.recyclerview.widget.RecyclerView.LayoutParams
import androidx.recyclerview.widget.RecyclerView.Recycler
import androidx.recyclerview.widget.RecyclerView.State
import com.fmt.mvi.learn.gobal.log
import com.scwang.smart.refresh.layout.util.SmartUtil.fling

const val ITEM_HEIGHT_PRE = 0.45f

class VerticalCardLayoutManager : LayoutManager() {


    //y轴偏移量
    private var mOffsetY = 0


    var mRv: RecyclerView? = null

    override fun onAttachedToWindow(view: RecyclerView?) {
        this.mRv = view
        super.onAttachedToWindow(view)
    }

    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        return RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
    }


    override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
        super.onLayoutChildren(recycler, state)
        if (state.itemCount == 0) {
            removeAndRecycleAllViews(recycler)
            return
        }
        fill(recycler, state, 0)

    }

    var firstLayoutViewPostion = 0
    var firstLayoutViewTop = 0
    var lastLayoutViewPosition = 0
    var lastLayoutViewBottom = 0


    private fun fill(recycler: Recycler, state: State, dy: Int) {

        val firstView = mRv?.getChildAt(0)
        if (firstView != null) {
            if (dy > 0) {//向上滑动
                if (firstView.bottom - dy <= 0) {//底部超出屏幕
                    firstLayoutViewPostion += 1
                    firstLayoutViewTop = firstView.bottom - dy
                } else {
                    firstLayoutViewTop -= dy
                }
            } else {

                if (firstLayoutViewPostion != 0 && (firstView.top - dy >= 0)) {//顶部超出屏幕
                    firstLayoutViewPostion -= 1
                    //计算出新的top
                    val view = recycler.getViewForPosition(firstLayoutViewPostion)
                    addView(view, 0)
                    measureChildWithMargins(view, 0, 0)
                    val viewHeight = getDecoratedMeasuredHeight(view)
                    firstLayoutViewTop = firstView.top - viewHeight
                }else{
                    firstLayoutViewTop -= dy
                }
            }
        }

        //暂时分离和回收有效item
        detachAndScrapAttachedViews(recycler)


        //根据mOffsetY 判断当前从第几个view显示
        val startCount = firstLayoutViewPostion
        var top = firstLayoutViewTop
        for (i in startCount.toInt() until state.itemCount) {
            //根据postion 获取view
            val itemView = recycler.getViewForPosition(i)
            //添加进去，当然里面不一定每次都是调用RecyclerView的addView方法的，
            //如果是从缓存区里面找到的，只需调用attachView方法把它重新连接上就行了。
            addView(itemView)
            //测量item，当然，也不是每次都会调用measure方法进行测量的，
            //它里面会判断，如果已经测量过，而且当前尺寸又没有收到更新的通知，就不会重新测量。
            measureChildWithMargins(itemView, 0, 0)
            val left = 0
            val right = left + getDecoratedMeasuredWidth(itemView)
            val bottom = top + getDecoratedMeasuredHeight(itemView)
            layoutDecorated(itemView, left, top, right, bottom)

//            if (top > 0) {
//                //根据top 距离父控件高度的百分比 来缩放view [0.75,1]
//                val scale = (1 - top / height.toFloat()) * (1 - 0.75f) + 0.75f
//                itemView.pivotY = itemView.height / 5f
//                itemView.pivotX = itemView.width / 2f
//                itemView.scaleX = scale
//                itemView.scaleY = scale
//            } else {
//                //根据移动出去的view 进行缩放
//                val scale = 1 + top / itemView.height.toFloat() * (1 - 0.4f)
//                itemView.scaleX = scale
//                itemView.scaleY = scale
//            }
            if (bottom > height) {
                lastLayoutViewPosition = i
                lastLayoutViewBottom = bottom
                "当前布局的最后一个view $lastLayoutViewPosition".log()
                break
            }
            top = bottom
        }
    }

    override fun canScrollVertically(): Boolean {
        return true
    }


    var mLastOffset = 0
    override fun scrollVerticallyBy(
        dy: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (dy == 0 || itemCount == 0) {
            return 0
        }
        var mDy = dy
        mLastOffset = mOffsetY
        updateOffsetY(mDy)
        mDy = mOffsetY - mLastOffset
        //滚动view
        fill(recycler, state, mDy)
        //回收view
        recycleChildren(recycler)
        return mDy
    }

    /**
     * 回收需回收的item
     */
    @Synchronized
    private fun recycleChildren(recycler: Recycler) {
        val scrapList = recycler.scrapList
        for (i in scrapList.indices) {
            val holder = scrapList[i]
            removeAndRecycleView(holder.itemView, recycler)
        }
    }

    //累加y轴偏移量
    private fun updateOffsetY(dy: Int) {
        if (isFlinging && !isFlingingEnable) {
            return
        }
        mOffsetY += dy
        if (mOffsetY < 0) {
            mOffsetY = 0
        }
        //向上滑动 判断最后一个是否滑动到底部
        if (dy > 0) {
            //获取最后一个view
            val lastView = getChildAt(childCount - 1) ?: return
            //获取该view的postion
            val lastViewPosition = getPosition(lastView)
            //判断是否滑动到底部
            if (lastViewPosition == itemCount - 1) {
                //获取最后一个view的底部
                val lastViewBottom = getDecoratedBottom(lastView)
                //判断是否滑动到底部，如果超出，修正
                if (lastViewBottom - dy <= height) {
                    mOffsetY -= dy;
                    mOffsetY += lastViewBottom - height
                }
            }
        }
    }

    private var isFlinging: Boolean = false
    private var isFlingingEnable: Boolean = true//是否支持惯性滑动
    override fun onScrollStateChanged(state: Int) {
        super.onScrollStateChanged(state)
        isFlinging = state == RecyclerView.SCROLL_STATE_SETTLING
        when (state) {
            RecyclerView.SCROLL_STATE_DRAGGING -> {
                cancelAnimal()
            }

            RecyclerView.SCROLL_STATE_SETTLING -> {//
                //根据离开时候的速度，判断是否需要惯性滑动
                if (!isFlingingEnable) {

                }
            }

            RecyclerView.SCROLL_STATE_IDLE -> {
//                //滑动停止，自动滚到到指定位置
//                val autoStopPosition = findAutoStopPosition()
//                smoothScrollToPosition(autoStopPosition)
            }
        }
    }


    var scrollAnimal: ValueAnimator? = null
    private fun cancelAnimal() {
        scrollAnimal?.cancel()
    }

    private fun smoothScrollToPosition(position: Int) {

        cancelAnimal()
        //计算需要滚动的距离
        val itemHeight = height * ITEM_HEIGHT_PRE
        val dy = position * itemHeight - mOffsetY

        val startOffset = mOffsetY
        scrollAnimal = ValueAnimator.ofFloat(0.0f, dy)
            .apply {
                duration = 200
                addUpdateListener {
                    mOffsetY = (startOffset + (it.animatedValue as Float)).toInt()
                    requestLayout()
                }

            }
        scrollAnimal?.start()

    }

    //找到当前需要滚动到的位置
    private fun findAutoStopPosition(): Int {
        val itemHeight = height * ITEM_HEIGHT_PRE
        val startCount = mOffsetY / itemHeight.toInt()
        val itemPassHeight = mOffsetY % itemHeight
        return if (itemPassHeight > itemHeight / 2) {//超出一半 滑动到下一个
            startCount + 1
        } else {//没有超出，将当前的滑动回来
            startCount
        }.let {
            var mIt = it
            if (mIt < 0) mIt = 0
            if (mIt > itemCount - 1) mIt = itemCount - 1
            mIt
        }
    }
}